/**
 * new关键字做了什么
 * (1) 创建一个新对象；
   (2) 将构造函数的作用域赋给新对象（因此 this 就指向了这个新对象） ；
   (3) 将这个新对象的__proto__成员指向了构造函数的prototype成员对象
   (4) 然后执行构造函数中的代码（为这个新对象添加属性，也就是会把代码全部作用于当前的实例对象上，this指向的是当前实例对象，所以会添加属性） ；
   (5) 返回新对象
 */
function show() {
    console.log("object");
    this.age = "zwz";
}
let s = new show();
console.dir(s);
console.dir(show);






/**
 * 该对象被类所引用，只有函数对象才可引用；
 * 在通过new创建一个类的实例对象的时候，prototype对象的成员都成为实例化对象的成员。
 * 同时，函数是一个对象，函数对象若直接声明成员，不用被实例化即可调用
 */
// function user() {}
// 
// // 通过prototype创建的对象只能通过实例化之后调用，直接调用会报错
// user.prototype.show = function () {
//     console.log("zwz");
// }

// let test = new user();
// test.show();




/**
 * __proto__服务于函数对象
 * prototype服务与函数实例化对象
 */
// function User() {}

// // __proto__服务于函数对象
// // 为User的原型添加show方法
// User.__proto__.show = function () {
//     console.log("未实例化");
// }

// // prototype服务与函数实例化对象
// User.prototype.show = function () {
//     console.log("实例化");
// }

// let test = new User();
// test.show();
// User.show();
// // 这个的意思为函数对象的prototype为实例化对象的__proto__原型
// // 意思就是函数对象的prototype里的方法与实例化对象的方法一模一样
// console.log(User.prototype == test.__proto__);


/**
 * 子级可以调用父级的方法，如果父级和子级有同名的方法，会采用就近原则，
 * 使用离对象本身最近的方法
 */
// let zwz = {
//     name: "zwz",
//     show: function () {
//         // this指向的是当前调用这个方法的对象
//         console.log(this.name);
//     }
// };
// let zcm = {
//     name: "zcm"
// };
// // 设置父级原型，第一个参数是子级，第二个参数是父级
// Object.setPrototypeOf(zcm, zwz);
// zcm.show();



/**
 * 实例对象的原型
 * Object.getPrototypeOf(test) == test.__proto__ == User.prototype
 * 
 * 函数本体
 * test.__proto__.constructor == User.prototype.constructor ==Object.getPrototypeOf(test).constructor == User
 */
// function User() {};
// let test = new User();
// 
// // 实例对象的原型就是User.prototype,里面的方法constructor指向函数本身，也就是User
// console.dir(test.__proto__.constructor == User);
// 
// // Object.getPrototypeOf(test)获取实例对象原型
// console.log(Object.getPrototypeOf(test) == User.prototype);


/**
 * 原型检测instanceof
 */
// function A() {}

// function B() {}

// let a = new A();
// // 将a赋值给B.prototype ,这里只是改变了B.prototype的值，不是把B.prototype变成了a
// // 所以b instanceof B的结果为true
// B.prototype = a;
// let b = new B();
// //instanceof 运算符用来检测 B.prototype 是否存在于参数 b 的原型链上。
// console.log(b instanceof B);
// console.dir();

// //       A.prototype
// //       /         \
// //       a       new A()
// //     /   \
// //   b     new B()



/**
 * 重复的方法可以放在原型链中创建
 */
// function User(name, age) {
//     this.name = name;
//     this.age = age;
// }
// User.prototype = {
//     constructor: User,
//     run: function () {
//         // 原型中的this永远指向调用这个方法的对象
//         console.log(this.name + "跑");
//     },
//     eat: function () {
//         console.log("吃");
//     }
// }
// let user = new User("zwz", 17);
// let zwz = new User("zcm", 18);

// console.dir(user.eat());

// function user() {}
// user.prototype.show = function () {
//     console.log("user");
// }

// function obj() {}
// // 使用现有的对象来提供新创建的对象的__proto__
// obj.prototype = Object.create(user.prototype);
// let object = new obj();
// object.show();
// console.dir(object);